﻿using System;
using System.Collections.Generic;
using RCSP.Common.Configurations;

namespace RCSP.Biz.Repositories
{
    public abstract class BaseRepository<T> : IRepository<T>
        where T : EntityBase, new()
    {
        protected readonly EntityMapping Mapping;
        private AppConfig config;

        /// <summary>
        ///     Creates new instance
        /// </summary>
        protected BaseRepository()
        {
            config = new AppConfig();
            Mapping = config.GetEntityMapping<T>();
        }

        #region IRepository<T> Members

        public T GetItem(int id)
        {
            throw new NotImplementedException();
        }

        public List<T> GetAllItemsByQuery(string query)
        {
            throw new NotImplementedException();
        }

        public void SaveItem(T entity)
        {
            throw new NotImplementedException();
        }

        public void DeleteItem(int id)
        {
            throw new NotImplementedException();
        }

        #endregion

        /*
        protected virtual void MapToEntity(DataRow dr, T entity)
        {
            //entity.UniqueId = dr.UniqueId;
            // properties dictionary for validation
            var propertiesDic = new Dictionary<string, string>();
            foreach (var prop in typeof(T).GetProperties())
                propertiesDic[prop.Name] = prop.Name;

            // map properties from configuration
            foreach (var propertyName in Mapping.PropertiesMapping.Keys)
            {
                if (!propertiesDic.ContainsKey(propertyName))
                    throw new ArgumentException(String.Format("Type '{0}' doesn't have public property with name '{1}'", typeof(T).FullName, propertyName));

                var propertyPath = Mapping.PropertiesMapping[propertyName].ColumnName.Split('.');
                var columnName = propertyPath[0];

                object value = dr[columnName];
                SPField currentField = null;
                if (dr.Field.ContainsField(columnName))
                    currentField = dr.Fields.GetField(columnName);

                if (currentField != null && currentField is SPFieldCalculated)
                {
                    try
                    {
                        value = currentField.GetFieldValueAsText(value);
                        var propertyType = typeof(T).GetProperty(propertyName).PropertyType;
                        value = TryConvertSimpleValue(value, propertyType);
                    }
                    catch (Exception ex)
                    {
                        throw new ArgumentNullException("Error on getting calculated value", ex);
                    }
                }
                else if (value != null)
                {
                    var propertyType = typeof(T).GetProperty(propertyName).PropertyType;
                    value = TryConvertSimpleValue(value, propertyType);
                    if (propertyType == typeof(LookUpItem))
                    {
                        value = TakeLookupValue(dr, columnName);
                    }
                    else if (propertyType == typeof(List<LookUpItem>))
                        value = TakeLookupValues(dr, columnName);
                    else if (propertyType == typeof(List<string>))
                        value = TakeValuesFromMultiChoice(dr, columnName);
                    else if (propertyType == typeof(List<PersonInfo>))
                        value = GetPersonCollection(dr, columnName);
                    else if (propertyType == typeof(PersonInfo))
                        value = GetPerson(dr, columnName);
                }

                try
                {
                    typeof(T).InvokeMember(
                        propertyName,
                        System.Reflection.BindingFlags.SetProperty,
                        null,
                        entity,
                        new object[] { value });
                }
                catch (Exception ex)
                {
                    throw new ArgumentNullException(String.Format("Error when setting property '{0}' value '{1}'", propertyName, value), ex);
                }
            }
        }

        /// <summary>
        /// Maps entity of type T to SPListItem
        /// </summary>
        protected virtual void MapToListItem(T entity, SPListItem item)
        {
            // base fields
            var allFields = item.ParentList.Fields;
            var editorField = allFields.GetFieldByInternalName("Editor");
            var authorField = allFields.GetFieldByInternalName("Author");
            if (SPContext.Current != null)
            {
                if (entity.UniqueId.HasValue)
                {
                    item[editorField.Title] = SPContext.Current.Web.CurrentUser;
                }
                else
                {
                    item[authorField.Title] = SPContext.Current.Web.CurrentUser;
                    item[editorField.Title] = SPContext.Current.Web.CurrentUser;
                }
            }

            // map properties from configuration
            foreach (var propertyName in Mapping.PropertiesMapping.Keys)
            {
                if (propertyName.ToLower() != "id")
                {
                    if (Mapping.PropertiesMapping[propertyName].IsReadOnly)
                        continue;
                    var columnName = Mapping.PropertiesMapping[propertyName].ColumnName;

                    var value = typeof(T).InvokeMember(
                        propertyName,
                        System.Reflection.BindingFlags.GetProperty,
                        null,
                        entity,
                        new object[] { });

                    if (value == null)
                    {
                        item[columnName] = null;
                        continue;
                    }

                    var propertyType = typeof(T).GetProperty(propertyName).PropertyType;
                    if (propertyType == typeof(double) || propertyType == typeof(double?) ||
                        propertyType == typeof(decimal) || propertyType == typeof(decimal?) ||
                        propertyType == typeof(float) || propertyType == typeof(float?))
                        item[columnName] = Convert.ToDecimal(value);
                    else if (propertyType == typeof(TimeSpan) || propertyType == typeof(TimeSpan?))
                    {
                        item[columnName] = value.ToString();
                    }
                    else if (propertyType == typeof(List<LookUpItem>))
                    {
                        item[columnName] = FormatValuesForMultipleLookup((List<LookUpItem>)value, item, columnName);
                    }
                    else if (propertyType == typeof(List<string>))
                    {
                        item[columnName] = FormatValuesForMultiChoice((List<string>)value);
                    }
                    else if (propertyType == typeof(List<PersonInfo>))
                    {
                        item[columnName] = FormatUserCollection((List<PersonInfo>)value, item);

                    }
                    else if (propertyType == typeof(PersonInfo))
                    {
                        var user = (PersonInfo)value;
                        SPUser spuser = item.Web.EnsureUser(user.LogOn);
                        item[columnName] = new SPFieldUserValue(item.Web, spuser.ID, spuser.LoginName);

                    }
                    else if (propertyType == typeof(LookUpItem))
                    {
                        var lookUpItem = (LookUpItem)value;
                        item[columnName] = FormatValuesForLookup(lookUpItem, item, columnName);
                    }
                    else if (propertyType == typeof(DateTime))
                    {
                        var datetimeValue = (DateTime)value;
                        if (datetimeValue == DateTime.MinValue || datetimeValue == null)
                            item[columnName] = null;
                        else
                            item[columnName] = datetimeValue;
                    }
                    else
                    {
                        item[columnName] = value;
                    }
                }
            }
        }*/
    }
}